2016/03/29

Recent entries from same category

  1. Go 言語プログラミングエッセンスという本を書きました。
  2. errors.Join が入った。
  3. unsafe.StringData、unsafe.String、unsafe.SliceData が入った。
  4. Re: Go言語で画像ファイルか確認してみる
  5. net/url に JoinPath が入った。

go-github という、Google が開発している GitHub API ライブラリがあるのですが、今回 filosottile さんがたった4行のコードで実行速度を4倍にするという pull-request を書きました。

いったいどういう事かというと、golang の json.Decoder を使って http.Response.Body から JSON を読み取ると最後の改行(EOF)が読み込まれずに残ってしまい、レスポンスを完全に読み切らないまま http.Response.Body.Close() が呼ばれてしまう。これはこれで別に問題のあるコードではないのですが、継続してリクエストを送る場合にレスポンスを完全に読み切っていなかった事でクライアントは物理切断してしまい TLS 接続が再利用されなくなります。この TLS 接続を再利用する為には残りのたった1バイトを読み捨ててあげる必要がある。そこで

defer func() {
    // Drain and close the body to let the Transport reuse the connection
    io.Copy(ioutil.Discard, resp.Body)
    resp.Body.Close()
}()

というコードになったという事です。個人的にはこれは golang 本体がやるべき仕事な気もするのでオススメはしませんし、今後 golang に何かしらの対応が入るのかもしれませんが、今すぐ高速な HTTP 通信が必要という方は試してみるのも良いかもしれません。

ちなみにこの件、Content-Length 分読み取って json.Unmarshal していれば発生しないはずですが json.Decoder のメモリを極力使わないというメリットが使えなくなるというのもあり一長一短ですね。

Posted at by